#ifndef GsgXMLWriter_defined
#define GsgXMLWriter_defined

/// Write tiny xml elements and attributes
class GsgXMLWriter : public GsgMeta
{
  /// type for stack of XML elements
  typedef std::vector<TiXmlElement *> elements_t;

  /// stack of XML elements
  elements_t elements;
  
public:
  /// constructor: which XML element to write to
  GsgXMLWriter(TiXmlElement *parent)
  {
    elements.push_back(parent);
  }
  
  /// make a new element to write to
  bool begin_element(const char *type_name)
  {
    TiXmlElement *parent = elements[elements.size()-2];
    assert(parent != NULL && "begin_element: parent is NULL");
    elements.back() = new TiXmlElement(type_name);
    parent->LinkEndChild( elements.back() );
    return true;
  }

  /// not used
  void end_element()
  {
  }

  /// write simple float type
  void attr(const char *name, float &value)
  {
    elements.back()->SetDoubleAttribute(name, value);
  }

  /// write simple int type
  void attr(const char *name, int &value)
  {
    elements.back()->SetDoubleAttribute(name, value);
  }
  
  /// write vectors of different types
  template <typename Type> void attr_helper(const char *name, Type *value, int n)
  {
    std::ostrstream stream;
    for (int i = 0; i != n; ++i)
    {
      stream << value[i] << " ";
    }
    stream << '\0';
    if (name[0] != '\0')
    {
      elements.back()->SetAttribute( name, stream.str() );
    } else
    {
      elements.back()->LinkEndChild( new TiXmlText(stream.str()) );
    }
  }

  /// write vectors of float type
  void attr(const char *name, float *value, int n)
  {
    attr_helper(name, value, n);
  }
  
  /// write vectors of int type
  void attr(const char *name, int *value, int n)
  {
    attr_helper(name, value, n);
  }
  
  /// write strings
  void attr(const char *name, std::string &value)
  {
    elements.back()->SetAttribute(name, value.c_str());
  }

  /// go down one level
  void push()
  {
    elements.push_back(NULL);
  }

  /// go back up one level
  void pop()
  {
    elements.pop_back();
  }

  /// always false for a writer
  bool is_reading()
  {
    return false;
  }

  /// not used for a writer
  const char *cur_element_name()
  {
    return NULL;
  }
};

#endif
